#pragma once
#include "comm/types.h"

#define IDT_TABLE_SIZE 128

#pragma pack(1)

//中断描述符
typedef struct  gate_descriptor
{
	uint16_t offset15_0;	//偏移量低16位
	uint16_t selector;		//段选择子
	uint16_t attr;			//属性
	uint16_t offset31_16;	//偏移量高16位
}gate_descriptor;

//异常信息
typedef struct exception_information
{
    uint32_t gs,fs,es,ds;
    uint32_t edi,esi,ebp,esp,ebx,edx,ecx,eax;
    uint32_t num,error_code;
    uint32_t eip,cs,eflags;
    uint32_t esp3,ss3;
}exception_information;

#pragma pack()

#define GATE_P_PRESENT (1 << 15)       //描述符是否有效
#define GATE_DPL0 (0 << 13)            //特权级0 
#define GATE_DPL3 (3 << 13)            //特权级3
#define GATE_TYPE_IDT (0xE << 8)       //中断门
#define GATE_TYPE_SYSCALL (0xc << 8)  //调用门

// 中断号码
#define IRQ0_DE             0
#define IRQ1_DB             1
#define IRQ2_NMI            2
#define IRQ3_BP             3
#define IRQ4_OF             4
#define IRQ5_BR             5
#define IRQ6_UD             6
#define IRQ7_NM             7
#define IRQ8_DF             8
#define IRQ10_TS            10
#define IRQ11_NP            11
#define IRQ12_SS            12
#define IRQ13_GP            13
#define IRQ14_PF            14
#define IRQ16_MF            16
#define IRQ17_AC            17
#define IRQ18_MC            18
#define IRQ19_XM            19
#define IRQ20_VE            20

#define IRQ0_TIMER                  0x20            //定时器
#define IRQ1_KYBOARD                0x21            //键盘中断
#define IRQ14_HARDDISK_PRIMARY      (0x20 + 14)     //磁盘


void set_gate_descriptor(gate_descriptor* desc,uint16_t selector,uint32_t offset,uint16_t attr);
void irq_init();
int irq_install(int irq_num,uint32_t handler);

void exception_handler_unknown (void);
void exception_handler_divzero (void);
void exception_handler_Debug (void);
void exception_handler_NMI (void);
void exception_handler_breakpoint (void);
void exception_handler_overflow (void);
void exception_handler_bound_range (void);
void exception_handler_invalid_opcode (void);
void exception_handler_device_unavailable (void);
void exception_handler_double_fault (void);
void exception_handler_invalid_tss (void);
void exception_handler_segment_not_present (void);
void exception_handler_stack_segment_fault (void);
void exception_handler_general_protection (void);
void exception_handler_page_fault (void);
void exception_handler_fpu_error (void);
void exception_handler_alignment_check (void);
void exception_handler_machine_check (void);
void exception_handler_smd_exception (void);
void exception_handler_virtual_exception (void);


//PIC控制器相关的寄存器及位配置
#define PIC0_ICW1			0x20
#define PIC0_ICW2			0x21
#define PIC0_ICW3			0x21
#define PIC0_ICW4			0x21
#define PIC0_OCW2			0x20
#define PIC0_IMR			0x21

#define PIC1_ICW1			0xa0
#define PIC1_ICW2			0xa1
#define PIC1_ICW3			0xa1
#define PIC1_ICW4			0xa1
#define PIC1_OCW2			0xa0
#define PIC1_IMR			0xa1

#define PIC_ICW1_ICW4		(1 << 0)		// 1 - 需要初始化ICW4
#define PIC_ICW1_ALWAYS_1	(1 << 4)		// 总为1的位
#define PIC_ICW4_8086	    (1 << 0)        // 8086工作模式

#define IRQ_PIC_START		0x20			// PIC中断起始号

#define PIC0_OCW2_EOI       (1 <<5)

//异常错误码

#define ERR_PAGE_P          (1 << 0)
#define ERR_PAGE_WR         (1 << 1)
#define ERR_PAGE_US         (1 << 2)

#define ERR_EXT             (1 << 0)
#define ERR_IDT             (1 << 1)

void  int_close(int int_num);
void  int_open(int int_num);

void open_global_int();
void close_global_int();

void pic_send_eoi(int int_num);

typedef uint32_t irq_state;
irq_state int_enter_protection();
void int_leave_protection(irq_state state);